/**
 * 活动对象
 *
 * @author fireway
 * @since 2019年 04月 25日 星期四 06:47:51 CST
 */
package concurrency;

import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class ActiveObjectDemo {
    private ExecutorService mExec = Executors.newSingleThreadExecutor();

    private Random mRand = new Random(47);

    public Future<Integer> calculateInt(final int x, final int y) {
        return mExec.submit(new Callable<Integer>() {
            @Override
            public Integer call() {
                System.out.println("starting " + x + " + " + y);
                pause(500);
                return x + y;
            }
        });
    }

    public Future<Float> calculateFloat(final float x, final float y) {
        return mExec.submit(new Callable<Float>() {
            @Override
            public Float call() {
                System.out.println("starting " + x + " + " + y);
                pause(2000);
                return x + y;
            }
        });
    }

    /**
     * Insert a random delay to produce the effect
     * of a calculation time
     */
    private void pause(int factor) {
        try {
            TimeUnit.MILLISECONDS.sleep(100 + mRand.nextInt(factor));
        } catch (InterruptedException e) {
            System.out.println("sleep() interrupted");
        }
    }

    public void shutdown() {
        mExec.shutdown();
    }

    public static void main(String[] args) {
        ActiveObjectDemo aod = new ActiveObjectDemo();
        // Prevents ConcurrentModificationException
        List<Future<?>> results = new CopyOnWriteArrayList<Future<?>>();

        for (float f = 0.0f; f < 1.0f; f += 0.2f) {
            results.add(aod.calculateFloat(f, f));
        }
        for (int i = 0; i < 5; i++) {
            results.add(aod.calculateInt(i, i));
        }

        System.out.println("All asynch calls made");

        while (results.size() > 0) {
            for (Future<?> f : results)
                if (f.isDone()) {
                    try {
                        System.out.println(f.get());
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    results.remove(f);
                }
        }
        aod.shutdown();
    }
}
